package com.service.totalauth.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.service.config.utils.*;
import com.service.totalauth.dao.ManageProgrammeInfoDao;
import com.service.totalauth.dto.*;
import com.service.totalauth.entity.CompanyInfo;
import com.service.totalauth.entity.ManageProgrammeInfo;
import com.service.totalauth.entity.ProgrammeApiBind;
import com.service.totalauth.enums.ProgrammeTypeEnum;
import com.service.totalauth.service.CompanyInfoService;
import com.service.totalauth.service.ManageProgrammeInfoService;
import com.service.totalauth.service.PortalUserService;
import com.service.totalauth.service.ProgrammeApiBindService;
import com.service.totalauth.vo.BindAccount;
import com.service.totalauth.vo.BindQyCorpInfoVo;
import com.service.totalauth.vo.QyCorpInfoDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.service.config.constant.Constant.PARAMETER_NOT_FOUND;
import static com.service.config.constant.Constant.parameterNotFound;

/**
 * 方案信息表(ManageProgrammeInfo)表服务实现类
 *
 * @author makejava
 * @since 2021-12-03 09:38:49
 */
@Service("manageProgrammeInfoService")
public class ManageProgrammeInfoServiceImpl implements ManageProgrammeInfoService {
    @Resource
    private ManageProgrammeInfoDao manageProgrammeInfoDao;
    @Value("${spring.fileSeverDomain}")
    private String fileSeverDomain;
    @Value("${spring.nginxUrl}")
    private String nginxUrl;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ProgrammeApiBindService programmeApiBindService;
    @Resource
    private CompanyInfoService companyInfoService;
    @Resource
    private PortalUserService portalUserService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ManageProgrammeInfo queryById(String id) {
        return this.manageProgrammeInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<ManageProgrammeInfo> queryAllByLimit(int offset, int limit) {
        return this.manageProgrammeInfoDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param manageProgrammeInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ManageProgrammeInfo insert(ManageProgrammeInfo manageProgrammeInfo) {
        this.manageProgrammeInfoDao.insert(manageProgrammeInfo);
        return manageProgrammeInfo;
    }

    /**
     * 修改数据
     *
     * @param manageProgrammeInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ManageProgrammeInfo update(ManageProgrammeInfo manageProgrammeInfo) {
        this.manageProgrammeInfoDao.update(manageProgrammeInfo);
        return this.queryById(manageProgrammeInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.manageProgrammeInfoDao.deleteById(id) > 0;
    }

    @Override
    public List<ManageProgrammeInfo> queryAll(ManageProgrammeInfo programmeInfoExamine) {
        return manageProgrammeInfoDao.queryAll(programmeInfoExamine);
    }

    @Override
    public void addDefaultProgrammeInfo(String userId,Integer isHave) {
        ManageProgrammeInfo programmeInfoExamine1 = manageProgrammeInfoDao.queryById("1");
        programmeInfoExamine1.setId(IdUtil.getStringId());
        programmeInfoExamine1.setProgrammeType(isHave);
        programmeInfoExamine1.setType(false);
        programmeInfoExamine1.setManageId(userId);
        programmeInfoExamine1.setAddTime(new Date());
        programmeInfoExamine1.setStatus(true);
        programmeInfoExamine1.setProgrammeType(0);
        programmeInfoExamine1.setProgrammeName("新增".concat(programmeInfoExamine1.getProgrammeName()));
        programmeInfoExamine1.setUpdateTime(new Date());
        programmeInfoExamine1.setProgrammeStatus(0);
        manageProgrammeInfoDao.insert(programmeInfoExamine1);
    }

    @Override
    public Result queryManageProgrammeInfo(String userId, String programmeInfoId, Integer type) {
        ManageProgrammeInfo programmeInfoExamine = new ManageProgrammeInfo();
        if (type != null) {
            programmeInfoExamine.setProgrammeType(type);
        }
        programmeInfoExamine.setManageId(userId);
        List<ManageProgrammeInfo> programmeInfoExamines = manageProgrammeInfoDao.queryAll(programmeInfoExamine);
        List<ProgrammeInfoExamineDto> programmeInfoExamineDtoList = ModelMapperUtil.strictMapList(programmeInfoExamines, ProgrammeInfoExamineDto.class);
        if (programmeInfoExamines.size() > 0) {
            if (programmeInfoId  != null && !"".equals(programmeInfoId)) {
                programmeInfoExamine.setId(programmeInfoId);
            }
            programmeInfoExamines.forEach(programmeInfoExamine1 -> {
                List<ProgrammeInfoExamineDto> collect = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                        programmeInfoExamineDto.getId().equals(programmeInfoExamine1.getId())).collect(Collectors.toList());
                collect.forEach(programmeInfoExamineDto -> {
                    programmeInfoExamineDto.setNewOne(false);
                    try {
                        Set<String> strings = redisUtil.redisLike(userId);
                        if(strings.stream().findFirst().isPresent()) {
                            String s = strings.stream().findFirst().get();
                            Object o = redisUtil.get(s);
                            UserDto  userDto = JsonXMLUtils.json2obj(o.toString(), UserDto.class);
                            programmeInfoExamineDto.setUserName(userDto.getUsername());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            });
            HashMap map = new HashMap();
            List<ProgrammeInfoExamineDto> programmeInfoExamineDtoCommonList = new ArrayList<>();
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 0).collect(Collectors.toList());
            map.put("Portal",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 1).collect(Collectors.toList());
            map.put("FeiShu",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 2).collect(Collectors.toList());
            map.put("DingDing",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 3).collect(Collectors.toList());
            map.put("APPList",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 4).collect(Collectors.toList());
            map.put("wechatCode",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 9).collect(Collectors.toList());
            map.put("qyWeChat",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 8).collect(Collectors.toList());
            map.put("wechatShare",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 6).collect(Collectors.toList());
            map.put("QQ",programmeInfoExamineDtoCommonList);
            programmeInfoExamineDtoCommonList = programmeInfoExamineDtoList.stream().filter(programmeInfoExamineDto ->
                    programmeInfoExamineDto.getProgrammeType() == 7).collect(Collectors.toList());
            map.put("ALI",programmeInfoExamineDtoCommonList);
            return Result.ok().setData(map);
        }
        return Result.ok();
    }

    @Override
    @Transactional
    public Result addManageProgrammeInfo(String userId, AddProgrammeInfoExamineDto addProgrammeInfoExamineDto) {
        ManageProgrammeInfo manageProgrammeInfo = ModelMapperUtil.strictMap(addProgrammeInfoExamineDto, ManageProgrammeInfo.class);
        manageProgrammeInfo.setId(IdUtil.getStringId());
        manageProgrammeInfo.setManageId(userId);
        manageProgrammeInfo.setAddTime(new Date());
        manageProgrammeInfo.setType(true);
        manageProgrammeInfo.setStatus(true);
        manageProgrammeInfo.setUpdateTime(new Date());
        manageProgrammeInfo.setProgrammeStatus(0);
        manageProgrammeInfoDao.insert(manageProgrammeInfo);
        return Result.ok();
    }

    /**
     * 查看该方案已绑定的账号和唯一url
     * @param userId
     * @param programmeInfoId
     * @return
     */
    @Override
    public Result getUrl(String userId, String programmeInfoId,Integer type) {
        if (programmeInfoId == null || "".equals(programmeInfoId)){
            return Result.failure(PARAMETER_NOT_FOUND,parameterNotFound);
        }
        ManageProgrammeInfo manageProgrammeInfo = manageProgrammeInfoDao.queryById(programmeInfoId); //查询方案
        CompanyInfo qyCorpInfo = new CompanyInfo();
        qyCorpInfo.setManageId(userId);
        qyCorpInfo.setType(type);
        qyCorpInfo.setcStatus(true);
        List<CompanyInfo> qyCorpInfoList = companyInfoService.queryAll(qyCorpInfo);
        if (manageProgrammeInfo.getProgrammeApiBindId() == null || "".equals(manageProgrammeInfo.getProgrammeApiBindId())) { // 判断绑定的信息
            return Result.failure("还未绑定方案，请前往绑定页面");
        }
        ProgrammeTypeEnum programmeTypeEnum = ProgrammeTypeEnum.get(manageProgrammeInfo.getProgrammeType());
        ProgrammeApiBind programmeApiBind = new ProgrammeApiBind();
        programmeApiBind.setManageId(userId);
        List<ProgrammeApiBind> programmeApiBindList = programmeApiBindService.queryAll(programmeApiBind); //查询绑定信息的中间表
        List<ScreenUserDto> screenUserDtoList = portalUserService.queryAll(userId);
        if (programmeApiBindList.size() > 0) {
            programmeApiBindList = programmeApiBindList.stream().filter(programmeApiBind1 -> programmeApiBind1.getProgrammeInfoId().equals(programmeInfoId)).collect(Collectors.toList());
        }
        List<BindQyCorpInfoVo> qyCorpInfoVos = ModelMapperUtil.strictMapList(programmeApiBindList, BindQyCorpInfoVo.class);
        JSONArray objects = JSONArray.parseArray(manageProgrammeInfo.getProgrammeApiBindId());
        List<String> stringList = new ArrayList<>();
        for (Object s : objects) {
            stringList.add(s.toString());
        }
        stringList.forEach(s -> {
            List<BindQyCorpInfoVo> collect = qyCorpInfoVos.stream().filter(bindQyCorpInfoVo -> bindQyCorpInfoVo.getId().equals(s)).collect(Collectors.toList());
            collect.forEach(programmeApiBind1 -> {
                List<CompanyInfo> collect1 = qyCorpInfoList.stream().filter(companyInfo -> companyInfo.getId().equals(programmeApiBind1.getCompanyInfoId())).collect(Collectors.toList());
                programmeApiBind1.setManageId(userId);
                programmeApiBind1.setProgrammeType(manageProgrammeInfo.getProgrammeType());
                if (collect1.size() > 0) {
                    if (collect1.get(0).getCpName() != null && !collect1.get(0).getCpName().equals("")){
                        programmeApiBind1.setCpName(collect1.get(0).getCpName());
                    }
                    programmeApiBind1.setOnlyUrl(fileSeverDomain.concat(nginxUrl).concat("/"+programmeTypeEnum.getDescription()+"?programmeInfoBindId=")
                            .concat(programmeApiBind1.getId()));
                }else {
                    programmeApiBind1.setOnlyUrl(fileSeverDomain.concat(nginxUrl).concat("/"+programmeTypeEnum.getDescription()+"?programmeInfoBindId=")
                            .concat(programmeApiBind1.getId()));
                }
                if (screenUserDtoList.size() > 0) {
                    List<ScreenUserDto> collect2 = screenUserDtoList.stream().filter(screenUserDto -> screenUserDto.getId().equals(programmeApiBind1.getPortalUserId())).collect(Collectors.toList());
                    boolean present = collect2.stream().findFirst().isPresent();
                    if (present) {
                        programmeApiBind1.setScreenUserDto(collect2.stream().findFirst().get());
                    }
                }
            });
        });
        List<ProgrammeApiBind> programmeApiBindList1 = ModelMapperUtil.strictMapList(qyCorpInfoVos, ProgrammeApiBind.class);
        updateBatch(programmeApiBindList1);
        return Result.ok().setData(qyCorpInfoVos);
    }

    private void updateBatch(List<ProgrammeApiBind> programmeApiBindList1) {
        programmeApiBindService.insertOrUpdateBatch(programmeApiBindList1);
    }

    /**
     * 方案绑定api账号、企业信息
     * @param userId
     * @param bindAccount
     * @return
     * @throws Exception
     */
    @Override
    public Result bindAccountAndProgramme(String userId, BindAccount bindAccount) throws Exception {
        List<ProgrammeApiBind> qyProgrammeApiBindList = ModelMapperUtil.strictMapList(bindAccount.getBindAccountList(), ProgrammeApiBind.class);
        ManageProgrammeInfo manageProgrammeInfo1 = manageProgrammeInfoDao.queryById(bindAccount.getProgrammeInfoId());
        if (manageProgrammeInfo1 == null) {
            return Result.failure("方案不存在，请重新获取数据");
        }
        if (manageProgrammeInfo1.getProgrammeApiBindId() != null && !"".equals(manageProgrammeInfo1.getProgrammeApiBindId())) {
            JSONArray objects = JSONArray.parseArray(manageProgrammeInfo1.getProgrammeApiBindId());
            List<String> stringList = new ArrayList<>();
            for (Object s : objects) {
                stringList.add(s.toString());
            }
            programmeApiBindService.deleteByBatchId(stringList); // 批量删除已经绑定的信息
        }
        List<String> stringList = new ArrayList<>();
        qyProgrammeApiBindList.forEach(qyProgrammeApiBind1 -> {
            qyProgrammeApiBind1.setBindTime(new Date()) ;
            qyProgrammeApiBind1.setId(IdUtil.getStringId());
            qyProgrammeApiBind1.setProgrammeInfoId(bindAccount.getProgrammeInfoId());
            stringList.add(qyProgrammeApiBind1.getId());
            qyProgrammeApiBind1.setManageId(userId);
        });
        ManageProgrammeInfo manageProgrammeInfo = new ManageProgrammeInfo();
        manageProgrammeInfo.setId(bindAccount.getProgrammeInfoId());
        manageProgrammeInfo.setProgrammeApiBindId(JsonXMLUtils.obj2json(stringList));
        manageProgrammeInfo.setProgrammeStatus(0);
        if (qyProgrammeApiBindList.size() > 0) {
            int insertBatch = programmeApiBindService.insertBatch(qyProgrammeApiBindList);
            if (insertBatch > 0) {
                manageProgrammeInfoDao.update(manageProgrammeInfo);
                return Result.ok();
            }
        }
        return Result.failure("批量绑定方案和api失败，请检查");
    }
    @Override
    @Transactional
    public Result putIssue(ApplicationProgrammeInfoDto applicationProgrammeInfoDto) {
        ManageProgrammeInfo manageProgrammeInfo = ModelMapperUtil.strictMap(applicationProgrammeInfoDto, ManageProgrammeInfo.class);
        manageProgrammeInfo.setProgrammeStatus(1);
        manageProgrammeInfo.setUpdateTime(new Date());
        manageProgrammeInfoDao.update(manageProgrammeInfo);
        return Result.ok();
    }

    @Override
    public Result queryPortalHtml(String programmeInfoBindId, Integer type) {
        if (programmeInfoBindId == null || "".equals(programmeInfoBindId) ||type == null) {
            return Result.failure("参数不对，请重新检查");
        }
        if (type != 0) {
            ProgrammeApiBind programmeApiBind2 = programmeApiBindService.queryById(programmeInfoBindId);
            if (programmeApiBind2 != null) {
                if (programmeApiBind2.getCompanyInfoId() != null && !programmeApiBind2.getCompanyInfoId().equals("")) {
                    String companyInfoId = programmeApiBind2.getCompanyInfoId();
                    CompanyInfo companyInfo = companyInfoService.queryById(companyInfoId);
                    if (!companyInfo.iscStatus()) {
                        return Result.failure("未查到相应信息，请重新校验参数");
                    }
                    QyCorpInfoDto qyCorpInfoDto = ModelMapperUtil.strictMap(companyInfo, QyCorpInfoDto.class);
                    return Result.ok().setData(qyCorpInfoDto);
                }
                return Result.failure("未查到相应信息，请重新校验参数");
            }
            return Result.failure("未查到相应信息，请重新校验参数");
        }
        return Result.ok("普通认证类型，不绑定应用信息");
    }

    @Override
    @Transactional
    public Result bindWeChatAndQy(String wechatId, String qyId, Integer type) {
        CompanyInfo companyInfo = new CompanyInfo();
        companyInfo.setId(wechatId);
        companyInfo.setCompanyInfoId(qyId);
        companyInfo.setType(type);
        companyInfo.setcStatus(true);
        companyInfo.setCpUpdateTime(new Date());
        companyInfo.setCpAddTime(new Date());
        companyInfo.setCpAddTime(new Date());
        companyInfoService.update(companyInfo);
        return Result.ok();
    }
}
